﻿using System.Collections.Generic;
using System.Xml;

using pt=System.UInt32;

namespace RDLC
{
   public enum RDLDataElementOutput
   {
      Output,
      NoOutput,
      ContentsOnly
   };

   public enum RDLDirection
   {
      Default,
      LTR,
      RTL
   };

   public class RDLTable : ReportItem
   {
      public string DataSetName; // Optional
      public string DetailDataCollectionName; // Optional
      public string DetailDataElementName; // Optional
      public RDLDataElementOutput? DetailDataElementOutput
      {
         get { return _DetailDataElementOutput; }
         set
         {
            if(!_DetailDataElementOutput.HasValue)
               _DetailDataElementOutput = new RDLDataElementOutput();
            _DetailDataElementOutput = value;
         }
      }
      private RDLDataElementOutput? _DetailDataElementOutput;
      public TableDetails Details;
      //note: Filters element not implemented yet
      public TableHeaderFooter Header; // Optional
      public TableHeaderFooter Footer; // Optional
      public bool? KeepTogether
      {
         get { return _KeepTogether; }
         set
         {
            if(!_KeepTogether.HasValue)
               _KeepTogether = new bool();
            _KeepTogether = value;
         }
      }
      private bool? _KeepTogether;
      public string NoRowsMessage; // Optional
      public bool? PageBreakAtEnd
      {
         get { return _PageBreakAtEnd; }
         set
         {
            if(!_PageBreakAtEnd.HasValue)
               _PageBreakAtEnd = new bool();
            _PageBreakAtEnd = value;
         }
      }
      private bool? _PageBreakAtEnd;
      public bool? PageBreakAtStart
      {
         get { return _PageBreakAtStart; }
         set
         {
            if (!_PageBreakAtStart.HasValue)
               _PageBreakAtStart = new bool();
            _PageBreakAtStart = value;
         }
      }
      private bool? _PageBreakAtStart;
      public List<TableColumn> TableColumns = new List<TableColumn>();
      //note: TableGroups element not implemented yet
      public string ToolTip; // Optional

      public RDLTable(string name, RDLPosition position, TableStyle style,
         TableDetails details, List<TableColumn> tableColumns)
         : base(name, "Table", position, style)
      {
         Details = details;
         TableColumns = tableColumns;
      }

      protected override void WriteDetails(XmlTextWriter writer)
      {
         if(DataSetName != null)
            writer.WriteElementString("DataSetName", DataSetName);

         if (DetailDataCollectionName != null)
            writer.WriteElementString("DetailDataCollectionName", DetailDataCollectionName);

         if (DetailDataElementName != null)
            writer.WriteElementString("DetailDataElementName", DetailDataElementName);

         if (DetailDataElementOutput.HasValue)
            writer.WriteElementString("DetailDataElementOutput", DetailDataElementOutput.Value.ToString());

         if (KeepTogether.HasValue)
            writer.WriteElementString("KeepTogether", KeepTogether.Value.ToString());

         if (NoRowsMessage != null)
            writer.WriteElementString("NoRowsMessage", NoRowsMessage);

         if (PageBreakAtEnd.HasValue)
            writer.WriteElementString("PageBreakAtEnd", PageBreakAtEnd.Value.ToString());

         if (PageBreakAtStart.HasValue)
            writer.WriteElementString("PageBreakAtStart", PageBreakAtStart.Value.ToString());

         if (!string.IsNullOrEmpty(ToolTip))
            writer.WriteElementString("ToolTip", ToolTip);

         if (Header != null)
            Header.Write(writer);

         Details.Write(writer);

         writer.WriteStartElement("TableColumns");

         foreach (TableColumn column in TableColumns)
            column.Write(writer);

         writer.WriteEndElement(); // TableColumns
      }
   }

   public class TableHeaderFooter
   {
      private bool _IsHeader;
      public TableHeaderFooter(bool isHeader)
      {
         _IsHeader = isHeader;
      }

      public List<TableRow> TableRows = new List<TableRow>();
      public bool? RepeatOnNewPage;

      public void Write(XmlTextWriter writer)
      {
         writer.WriteStartElement(_IsHeader ? "Header" : "Footer");

         if (RepeatOnNewPage.HasValue)
            writer.WriteElementString("RepeatOnNewPage", RepeatOnNewPage.Value.ToString().ToLower());

         writer.WriteStartElement("TableRows");

         foreach (TableRow row in TableRows)
         {
            row.Write(writer);
         }

         writer.WriteEndElement(); // TableRows
         writer.WriteEndElement(); // Header / Footer
      }
   }

   public class TableColumn
   {
      public bool? FixedHeader
      {
         get { return _FixedHeader; }
         set
         {
            if (!_FixedHeader.HasValue)
               _FixedHeader = new bool();
            _FixedHeader = value;
         }
      }
      private bool? _FixedHeader;
      public RDLVisibility Visibility; // Optional
      public pt? Width
      {
         get { return _Width; }
         set
         {
            if (!_Width.HasValue)
               _Width = new pt();
            _Width = value;
         }
      }
      private pt? _Width;

      public void Write(XmlTextWriter writer)
      {
         writer.WriteStartElement("TableColumn");

         if (Width.HasValue)
            writer.WriteElementString("Width", Width.Value + "pt");

         if(Visibility != null)
            Visibility.Write(writer);

         writer.WriteEndElement(); // TableColumn
      }
   }

   public class TableStyle : RDLStyle
   {
      public RDLColor? BackgroundColor
      {
         get { return _BackgroundColor; }
         set
         {
            if (!_BackgroundColor.HasValue)
               _BackgroundColor = new RDLColor();
            _BackgroundColor = value;
         }
      }
      private RDLColor? _BackgroundColor;
      public RDLImage BackgroundImage;
      public RDLPadding Padding;

      public TableStyle()
      {

      }

      public TableStyle(RDLBorderColor borderColor, RDLBorderStyle borderStyle, RDLBorderWidth borderWidth)
         : base(borderColor, borderStyle, borderWidth)
      {
      }

      protected override void WriteDetails(XmlTextWriter writer)
      {
         if (BackgroundColor.HasValue)
            writer.WriteElementString("BackgroundColor", BackgroundColor.Value.ToString());

         if (BackgroundImage != null)
            BackgroundImage.Write(writer);

         if(Padding != null)
            Padding.Write(writer);
      }
   }

   public class TableDetails
   {
      public RDLGrouping Grouping; // Optional
      //public RDLSorting Sorting note: RDLSorting not implemented
      public List<TableRow> TableRows = new List<TableRow>();
      public RDLVisibility Visibility; // Optional

      public void Write(XmlTextWriter writer)
      {
         writer.WriteStartElement("Details");

         writer.WriteStartElement("TableRows");

         foreach (TableRow row in TableRows)
         {
            row.Write(writer);
         }

         if(Visibility != null)
            Visibility.Write(writer);

         writer.WriteEndElement(); // TableRows
         writer.WriteEndElement(); // Details
      }
   }

   public class TableRow
   {
      public double Height;

      public List<TableCell> TableCells = new List<TableCell>();
      public RDLVisibility Visibility; // Optional

      public void Write(XmlTextWriter writer)
      {
         writer.WriteStartElement("TableRow");

         writer.WriteStartElement("TableCells");
         foreach (TableCell cell in TableCells)
         {
            cell.Write(writer);
         }
         writer.WriteEndElement(); // TableCells

         if(Visibility != null)
            Visibility.Write(writer);
         
         writer.WriteElementString("Height", Height + "pt");

         writer.WriteEndElement(); // TableRow
      }
   }

   public class TableCell
   {
      public uint? ColSpan
      {
         get { return _ColSpan; }
         set
         {
            if(!_ColSpan.HasValue)
               _ColSpan = new uint();
            _ColSpan = value;
         }
      }
      private uint? _ColSpan;

      public RDLReportItems ReportItems = new RDLReportItems();

      public TableCell(ReportItem item)
      {
         ReportItems.Add(item);
      }

      public void Write(XmlTextWriter writer)
      {
         writer.WriteStartElement("TableCell");
         
         if(ColSpan.HasValue)
            writer.WriteElementString("ColSpan", ColSpan.Value.ToString());

         ReportItems.Write(writer);

         writer.WriteEndElement(); // TableCell
      }
   }

   public class RDLGrouping
   {
      //note: Custom element not implemented
      public string DataCollectionName; // Optional
      public string DataElementName; // Optional
      public RDLDataElementOutput? DataElementOutput;
      //note: Filters element not implemented
      //note: GroupExpressions element not implemented
      public bool? PageBreakAtEnd;
      public bool? PageBreakAtStart;
      public string Parent; // Optional
   }
}
